package Connection;

import java.io.DataOutputStream;
import java.io.IOException;

import sharedData.DebugItem;
import sharedData.IDataItem;
import sharedData.MapData;
import sharedData.SharedConstants;
import data.IDataQueue;

/**
 * Thread that handles sending data.
 * 
 * @author Didzis Petkus, Danny Johansen, Liviu Berheci
 * 
 */
public class DataParser extends Thread {

	private boolean sending;
	private Connector con;
	private IDataQueue dataQueue;

	/**
	 * Constructor.
	 * 
	 * @param con
	 *            - bluetooth connector object
	 * @param queue
	 *            - queue holding data to send
	 */
	public DataParser(Connector con, IDataQueue queue) {
		this.con = con;
		this.dataQueue = queue;
		this.sending = false;
	}

	@Override
	public void run() {
		while (sending) {
			processData();
		}
	}

	/**
	 * Handles the data in data queue, if any.
	 */
	private void processData() {
		while (dataQueue.getSize() > 0) {
			sendItem(dataQueue.poll());
		}
	}

	/**
	 * Handles data sending according to its type.
	 * 
	 * @param item
	 *            - the given IDataItem object
	 */
	private void sendItem(IDataItem item) {
		if (item == null) {
			return;
		}
		if (item.getType() == SharedConstants.DATA_TYPE_MAP_DATA) {
			sendMapData((MapData) item);
		} else if (item.getType() == SharedConstants.DATA_TYPE_DEBUG) {
			sendDebugData((DebugItem) item);
		}
	}

	/**
	 * Sends the given DebugItem object using DataOutputStream from Connector
	 * object.
	 * 
	 * @param data
	 *            - DebugItem object to send
	 */
	private void sendDebugData(DebugItem data) {
		try {
			DataOutputStream out = con.getOutStream();

			out.writeByte(data.getType());
			out.writeFloat(data.getX());
			out.writeFloat(data.getY());
			out.writeFloat(data.getHeading());
			out.writeBytes(data.getMessage());

			out.flush();

		} catch (IOException e) {
			// Sound.twoBeeps();
			// System.err.println("Error sending data");
		}
	}

	/**
	 * Sends the given MapData object using DataOutputStream from Connector
	 * object.
	 * 
	 * @param data
	 *            - MapData object to send
	 */
	private void sendMapData(MapData data) {
		try {
			DataOutputStream out = con.getOutStream();

			out.writeByte(data.getType());
			out.writeFloat(data.getX());
			out.writeFloat(data.getY());
			out.writeFloat(data.getHeading());
			out.writeFloat(data.getLeftUssr());
			out.writeFloat(data.getRightUssr());
			out.writeFloat(data.getCenterUssr());

			out.flush();

		} catch (IOException e) {
			// Sound.twoBeeps();
			// System.err.println("Error sending data");
		}
	}

	/**
	 * Returns boolean true, if thread is running and processing data otherwise
	 * false.
	 * 
	 * @return the sending - Boolean true, if thread is running and processing
	 */
	public boolean isSending() {
		synchronized (this) {
			return sending;
		}
	}

	/**
	 * Sets the thread to process and send data.
	 * @param sending - 
	 */
	public void setSending(boolean sending) {
		synchronized (this) {
			this.sending = sending;
		}
	}

}
